/*
Copyright [2012] [Reimar Klammer / David Laubichler]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

//Ant.cpp
#pragma once
#include "stdafx.h"
#include "Field.h"
#include "Food.h"
#include "Ant.h"
#include "Environment.h"
#include "AntHive.h"
#include "Field.h"
#include "AntSimulationBaseItem.h"
#include "PlaceableObject.h"
#include "Creator.h"
#include <sstream>
#include <iostream>

Ant::Ant(Field* field) : PlaceableObject(field)
{
	m_TimeToLife = 100;
	hasFood = false;
	m_Food = NULL;
}


Ant::~Ant(void)
{	
	Field* f = this->GetActualField();
	f->RemoveItem(this);
}

void Ant::LayDownFood() 
{
	if(m_Food!=NULL)
	{
		Field* af = this->GetActualField();
		if(af!=NULL)
		{
			AntHive* hive = af->getHive();
			if(hive!=NULL)
			{
				hive->placeFood(m_Food);
				m_Food = NULL;
				return;
			}
			else
			{
				af->placeFood(m_Food);
				m_Food = NULL;
				return;
			}
		}
	}
}



void Ant::TakeFood(){
	//m_Food* = Food::GiveFood();
	hasFood=1;
}



void Ant::Simulate()
{
	if(this->GetActualField()!=NULL)
	{
		Field* old = this->GetActualField();
		old->RemoveItem(this);
		//this->SetActualField(this->GetActualField()->GetNextField());
		if(m_Food==NULL)	// Ameise hat noch kein Food
			this->SetActualField(this->getNextField());	// Ant kuemmert sich um NextField
		else
			this->SetActualField(this->getHome());	// Ant geht gleichen Weg heim

		std::cout <<"Moving from "; old->WritePosition(); std::cout << "to: "; this->GetActualField()->WritePosition(); std::cout << std::endl;
		m_TimeToLife--;
		Field* f = this->GetActualField();
		AntHive* h = f->getHive();
		if(h!=NULL)
		{
			std::cout << "Found Hive on "; f->WritePosition(); std::cout<<endl;
			m_WayHome.clear();
			m_TimeToLife = 100;
			if(m_Food!=NULL)
			{

				h->placeFood(m_Food);
				m_Food = NULL;
			}

		}
		if(m_Food == NULL)
		{
			m_Food = f->getFood();
			if(m_Food!=NULL)
			{
				std::cout << "Found food on "; f->WritePosition(); std::cout<<endl;
			}
		}

		if(m_Food!=NULL)
		{
			this->GetActualField()->SetPheromones((int)(m_TimeToLife/10));
		}

	}
	if(m_TimeToLife<=0)
	{
		Field* f = this->GetActualField();
		f->placeFood(Creator::Instance()->CreateFood(30,f));		// Ameise Tod und wird zu Futter
		std::cout << "Ant converted to food on "; this->GetActualField()->WritePosition(); std::cout<<endl;

		Environment::Instance()->AddItemToDelete(this);
	}



	//getchar();
}

Field* Ant::getNextField()
{
	//getchar();

	int allPheromones = 0;	// alle Pheromone in der Umgebung zaehlen
	Field* af = this->GetActualField();
	if(af==NULL)
		return NULL;

	for(std::list<Field*>::iterator iter = m_WayHome.begin();iter!=m_WayHome.end();iter++)
	{
		Field* lf = dynamic_cast<Field*>(*iter);
		if(lf!=NULL && lf==af)
		{
			do
			{
				m_WayHome.pop_back(); // Ameise ist Schleife gelaufen
				//std::cout<< m_WayHome.size() << " ";
			}while(m_WayHome.back()!=af);	//TODO: David: Da hat er noch irgendein Problem weil er bis zu einem Feld popt das es nicht gibt
			m_WayHome.pop_back(); // Actual Filed wird gepopt weils danach wieder hinzugefuegt wird.

			std::cout<< "Loop found at "; af->WritePosition(); std::cout<<endl;
			break;
		}

	}

	m_WayHome.push_back(af);	// merken fuer den Heimweg



	if(m_LastField!=(af->getNorth()) && af->getNorth()!=NULL)
		allPheromones = allPheromones + af->getNorth()->getPheromones();

	if(m_LastField!=af->getEast()&& af->getEast()!=NULL)
		allPheromones = allPheromones + af->getEast()->getPheromones();

	if(m_LastField!=af->getSouth()&& af->getSouth()!=NULL)
		allPheromones = allPheromones + af->getSouth()->getPheromones();

	if(m_LastField!=af->getWest()&& af->getWest()!=NULL)
		allPheromones = allPheromones + af->getWest()->getPheromones();

	//std::cout << "Pheromones around actual Field: " << allPheromones << std::endl;

	// Fenster fuer Auswahl des naechsten Feldes berechnen
	float range_North=0;
	float range_East=0;
	float range_South=0;
	float range_West=0;

	if(m_LastField!=(af->getNorth()) && af->getNorth()!=NULL && allPheromones > 0)
		range_North = (af->getNorth()->getPheromones())/(float)allPheromones;

	if(m_LastField!=af->getEast()&& af->getEast()!=NULL && allPheromones > 0)
		range_East = af->getEast()->getPheromones()/(float)allPheromones;

	if(m_LastField!=af->getSouth()&& af->getSouth()!=NULL && allPheromones > 0)
		range_South = af->getSouth()->getPheromones()/(float)allPheromones;

	if(m_LastField!=af->getWest()&& af->getWest()!=NULL && allPheromones > 0)
		range_West = af->getWest()->getPheromones()/(float)allPheromones;

	//float random = (rand() %2);
	float random = (float)rand()/(float)RAND_MAX;	//Zufallszahl zwischen 0-1 fuer Auswahl des Bereiches

	if(m_LastField!=(af->getNorth()) && af->getNorth()!=NULL && (random-range_North<=0))
	{
		m_LastField=af;
		//std::cout << "Going to Field North" << std::endl;
		return af->getNorth();
	}

	else if(m_LastField!=(af->getEast()) && af->getEast()!=NULL && (random-range_North-range_East<=0))
	{
		m_LastField=af;
		//std::cout << "Going to Field East" << std::endl;
		return af->getEast();
	}

	else if(m_LastField!=(af->getSouth()) && af->getSouth()!=NULL && (random-range_North-range_East-range_South<=0))
	{
		m_LastField=af;
		//std::cout << "Going to Field South" << std::endl;
		return af->getSouth();
	}

	else if(m_LastField!=(af->getWest()) && af->getWest()!=NULL && (random-range_North-range_East-range_South-range_West<=0))
	{
		m_LastField=af;
		//std::cout << "Going to Field West" << std::endl;
		return af->getWest();
	}

	else
	{ // sollte doch einmal ein Problem auftreten mit der Auswahl des neuen Feldes
		//std::cout << "Going to Random Field" << std::endl;
		while(true)
		{
			int random = 1 + rand() % 4;

			switch (random)
			{
			case 1:
				if(af->getNorth()!=NULL)
				{
					m_LastField=af;
					return af->getNorth();
				}
				break;
			case 2:
				if(af->getSouth()!=NULL)
				{
					m_LastField=af;
					return af->getSouth();
				}
				break;
			case 3:
				if(af->getWest()!=NULL)
				{
					m_LastField=af;
					return af->getWest();
				}
				break;
			case 4:
				if(af->getEast()!=NULL)
				{
					m_LastField=af;
					return af->getEast();
				}
				break;
			default:
				break;
			}
		}
	}
}

Field* Ant::getHome()
{

	Field* af = this->GetActualField();
	if(af==NULL)
		return NULL;

	if(m_WayHome.empty())
		return af;

	Field* next = m_WayHome.back();
	if (next==NULL)
		return af;

	if(m_TimeToLife<m_WayHome.size())
	{
		std::cout << "Heading home useless due to the far way: " << m_TimeToLife<< " TTL vs. " << m_WayHome.size() << " Steps Home" << std::endl;
		m_TimeToLife=0;	// Pech fuer die Ameise
	}

	m_WayHome.pop_back();
	//std::cout << "Ant on her way home" << std::endl;
	return next;
}

void Ant::GetXml(std::string* s)
{
	std::stringstream strst;

	strst<<"<Ant " << "X=\""<<this->GetActualField()->getX() << "\" Y=\""<< this->GetActualField()->getY() << "\"/>";

	s->append(strst.str());
	s->append("\n");
}